package com.smart.service.impl;

import com.google.common.collect.Lists;
import com.smart.common.enums.ConstructionStatusEnum;
import com.smart.common.enums.ProjectEngineeringTypeEnum;
import com.smart.common.utils.AssertUtil;
import com.smart.context.SessionContext;
import com.smart.helper.CommonUtil;
import com.smart.mapper.*;
import com.smart.model.convert.ProjectConvert;
import com.smart.model.customdo.PageHomeKeyValue;
import com.smart.model.domain.ProjectDO;
import com.smart.model.dto.WeekRangeDTO;
import com.smart.model.vo.DictItemVO;
import com.smart.model.vo.IndexStatisticalAnalysisVO;
import com.smart.model.vo.ProjectVO;
import com.smart.model.vo.SuperviseHomePageVO;
import com.smart.service.DictItemService;
import com.smart.service.HomePageService;
import com.smart.utils.DateUtils;
import com.smart.utils.ProjectGrouper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author: zyh
 * @date: 2023-07-02
 */
@Service
public class HomePageServiceImpl implements HomePageService {

    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ManageUserRegistrationMapper registrationMapper;
    @Autowired
    private DictItemService dictItemService;
    @Autowired
    private HotWorkMapper hotWorkMapper;
    @Autowired
    private JiansheProjectMapper jiansheProjectMapper;
    @Autowired
    private StreetMapper streetMapper;

    /**
     * 云服务首页
     *
     * @return
     */
    @Override
    public Object getServiceHomepage() {
        Long projectId = SessionContext.getProjectId();
        List<DictItemVO> personJob = dictItemService.queryDictItemByDictCode("USER_JOB");//人员职务

        //项目人员统计
        List<String> personList = registrationMapper.selectEightWeeklyDataByProjectId(projectId);
        PageHomeKeyValue personCount = PageHomeKeyValue.builder().name("总数").value(personList.size()).build();
        Map<String, Long> personMap = personList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> personPageList = personMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(personJob.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        personPageList.add(personCount);

        //项目人员流动性统计
        //最近八周的时间范围
        List<Map<String, Date>> weekRanges = getWeekRanges();

        List<String> weekRange = getWeekRange();
        List<Integer> notLeave = new ArrayList<>();
        List<Integer> leave = new ArrayList<>();
        //全区项目人员流动性统计
        weekRanges.forEach(week -> {
            Date startDate = week.get("startDate");
            Date endDate = week.get("endDate");
            //在场
            Integer leaveCount = registrationMapper.selectEightWeeklyData(1, projectId, startDate.toString(),
                    endDate.toString());
            //离场
            Integer notLeaveCount = registrationMapper.selectEightWeeklyData(0, projectId, startDate.toString(),
                    endDate.toString());
            notLeave.add(notLeaveCount);
            leave.add(leaveCount);
        });

        Map<String, Object> flowMap = new HashMap<>();
        flowMap.put("notLeave", leave);
        flowMap.put("leave", notLeave);
        flowMap.put("weeks", weekRange);

        //项目动火作业统计
        List<Integer> hotWorkData = new ArrayList<>();
        weekRanges.forEach(week -> {
            Date startDate = week.get("startDate");
            Date endDate = week.get("endDate");
            Integer dateList = hotWorkMapper.selectEightWeeklyData(projectId, startDate, endDate);
            hotWorkData.add(dateList);
        });
        Map<String, Object> hotWorkMap = new HashMap<>();
        hotWorkMap.put("hotWorkData", hotWorkData);
        hotWorkMap.put("weeks", weekRange);

        //最后更新时间
        Date lastDate = registrationMapper.getLastDate(projectId);
        if (ObjectUtils.isEmpty(lastDate)) {
            lastDate = DateUtils.getNowDate();
        }
        return SuperviseHomePageVO.builder().projectPersonList(personPageList).projectPersonFlowMap(flowMap).projectHotWorkCountMap(hotWorkMap).lastDate(lastDate).build();
    }

    /**
     * 云管理首页查询
     *
     * @return
     */
    @Override
    public Object getManageHomepage() {
        Long jiansheUnitId = SessionContext.getJiansheUnitId();
        AssertUtil.assertNotNull(jiansheUnitId, "建设单位用户登录使用");
        List<DictItemVO> personJob = dictItemService.queryDictItemByDictCode("USER_JOB");//人员职务
        List<Long> projectIds = jiansheProjectMapper.selectAllProjectId(jiansheUnitId);
        if (ObjectUtils.isEmpty(projectIds)) {
            return SuperviseHomePageVO.builder().lastDate(DateUtils.getNowDate()).build();
        }
        if (ObjectUtils.isEmpty(projectIds)) {
            return SuperviseHomePageVO.builder().lastDate(DateUtils.getNowDate()).build();
        }
        List<PageHomeKeyValue> personPageList = new ArrayList<>();
        AtomicReference<Integer> count = new AtomicReference<>(0);
        projectIds.forEach(projectId -> {
            //工程人员统计
            List<String> personList = registrationMapper.selectEightWeeklyDataByProjectId(projectId);
            Map<String, Long> personMap = personList.stream().collect(Collectors.groupingBy(item -> item,
                    Collectors.counting()));
            List<PageHomeKeyValue> personCountList = personMap.entrySet().stream()
                    .map(entry -> new PageHomeKeyValue(personJob.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                    .collect(Collectors.toList());
            personPageList.addAll(personCountList);
            count.set(count.get() + personList.size());
        });
        PageHomeKeyValue personCount = PageHomeKeyValue.builder().name("总数").value(count.get()).build();
        personPageList.add(personCount);

        List<Map<String, Date>> weekRanges = getWeekRanges();

        List<String> weekRange = getWeekRange();

        //项目人员流动性统计
        List<Integer> notLeave = new ArrayList<>();
        List<Integer> leave = new ArrayList<>();
        //全区项目人员流动性统计
        weekRanges.forEach(week -> {
            Date startDate = week.get("startDate");
            Date endDate = week.get("endDate");
            //在场
            Integer leaveCount = registrationMapper.selectEightWeeklyDataByProjectIds(1, projectIds,
                    startDate.toString(), endDate.toString());
            //离场
            Integer notLeaveCount = registrationMapper.selectEightWeeklyDataByProjectIds(0, projectIds,
                    startDate.toString(), endDate.toString());
            notLeave.add(notLeaveCount);
            leave.add(leaveCount);
        });
        Map<String, Object> flowMap = new HashMap<>();
        flowMap.put("notLeave", leave);
        flowMap.put("leave", notLeave);
        flowMap.put("weeks", weekRange);

        //项目动火作业统计
        List<Integer> hotWorkData = new ArrayList<>();
        weekRanges.forEach(week -> {
            Date startDate = week.get("startDate");
            Date endDate = week.get("endDate");
            Integer dateList = hotWorkMapper.selectEightWeeklyDataByProjectIds(projectIds, startDate, endDate);
            hotWorkData.add(dateList);
        });
        Map<String, Object> hotWorkMap = new HashMap<>();
        hotWorkMap.put("hotWorkData", hotWorkData);
        hotWorkMap.put("weeks", weekRange);
        //最后更新时间
        Date lastDate = registrationMapper.getLastDateByProjectids(projectIds);
        if (ObjectUtils.isEmpty(lastDate)) {
            lastDate = DateUtils.getNowDate();
        }
        return SuperviseHomePageVO.builder().projectPersonList(personPageList).projectPersonFlowMap(flowMap).projectHotWorkCountMap(hotWorkMap).lastDate(lastDate).build();
    }

    /**
     * 运营管理首页
     *
     * @return
     */
    @Override
    public Object getOperateHomepage() {
        List<DictItemVO> buildStatus = dictItemService.queryDictItemByDictCode("BUILD_TYPE");//施工状态
        List<DictItemVO> buildsType = dictItemService.queryDictItemByDictCode("PROJECT_TYPE");//工程类型

        //工程状态统计
        List<String> projectList = projectMapper.selectAllBuildStatus();
        Map<String, Long> statusMap = projectList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> resultList = statusMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(buildStatus.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        PageHomeKeyValue statusCount = PageHomeKeyValue.builder().name("总数").value(projectList.size()).build();
        resultList.add(statusCount);

        //工程类型统计
        List<String> typeList = projectMapper.selectAllBuildType();
        Map<String, Long> typeMap = typeList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> typePageList = typeMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(buildsType.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        PageHomeKeyValue typeCount = PageHomeKeyValue.builder().name("总数").value(typeList.size()).build();
        typePageList.add(typeCount);
        return SuperviseHomePageVO.builder().projectStatusList(resultList).projectTypeList(typePageList).build();
    }

    /**
     * 大屏左侧三个饼状图
     *
     * @return
     */
    @Override
    public Object getlargeScreenLeft() {
        List<DictItemVO> buildStatus = dictItemService.queryDictItemByDictCode("BUILD_TYPE");//施工状态
        List<DictItemVO> buildsType = dictItemService.queryDictItemByDictCode("PROJECT_TYPE");//工程类型
        List<DictItemVO> personJob = dictItemService.queryDictItemByDictCode("USER_JOB");//人员职务
        //工程状态统计
        List<String> projectList = projectMapper.selectAllBuildStatus();
        Map<String, Long> statusMap = projectList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> resultList = statusMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(buildStatus.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        PageHomeKeyValue statusCount = PageHomeKeyValue.builder().name("总数").value(projectList.size()).build();
        resultList.add(statusCount);

        //工程类型统计
        List<String> typeList = projectMapper.selectAllBuildType();
        Map<String, Long> typeMap = typeList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> typePageList = typeMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(buildsType.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        PageHomeKeyValue typeCount = PageHomeKeyValue.builder().name("总数").value(typeList.size()).build();
        typePageList.add(typeCount);

        //项目人员分布
        //项目人员分布
        List<Map<String, Object>> personList = registrationMapper.selectProjectPerson();
//        Map<String, Long> personMap  = personList.stream().collect(Collectors.groupingBy(item -> item, Collectors
//        .counting()));
//        List<PageHomeKeyValue> personPageList = personMap.entrySet().stream()
//                .map(entry -> new PageHomeKeyValue(personJob.stream().filter(dictItemVO -> entry.getKey().equals
//                (dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry
//                .getValue()))
//                .collect(Collectors.toList());
        AtomicLong all = new AtomicLong(0);
        List<PageHomeKeyValue> list = new ArrayList<>();
        personList.forEach(a -> {
            all.addAndGet((Long) a.get("num"));
            PageHomeKeyValue keyValue = new PageHomeKeyValue();
            keyValue.setName(String.valueOf(a.get("name")));
            keyValue.setValue(a.get("num"));
            list.add(keyValue);
        });
        PageHomeKeyValue personCount = PageHomeKeyValue.builder().name("总数").value(all.get()).build();
        list.add(personCount);

        return SuperviseHomePageVO.builder().projectStatusList(resultList).projectTypeList(typePageList)
                .projectPersonList(list).build();
    }

    /**
     * 大屏列表
     *
     * @return
     */
    @Override
    public Object getlargeScreenList() {
        List<ProjectDO> projectDOList = projectMapper.selectByStatus();
        List<ProjectVO> projectVOList = ProjectConvert.buildProjectVoList(projectDOList);
        Map<String, List<ProjectVO>> listMap = projectVOList.stream()
                .collect(Collectors.groupingBy(ProjectVO::getConstructionStatus));
        List<ProjectVO> list = new ArrayList<>();
        List<ProjectVO> running = listMap.get("RUNNING");
        if (!ObjectUtils.isEmpty(running)) {
            Map<Boolean, List<ProjectVO>> booleanListMap = ProjectGrouper.groupProjectsByScale(running);
            extracted(list, booleanListMap);
        }

        List<ProjectVO> waitAccept = listMap.get("WAIT_ACCEPT");
        if (!ObjectUtils.isEmpty(waitAccept)) {
            Map<Boolean, List<ProjectVO>> booleanListMap = ProjectGrouper.groupProjectsByScale(waitAccept);
            extracted(list, booleanListMap);
        }
        List<ProjectVO> stop = listMap.get("STOP");
        if (!ObjectUtils.isEmpty(stop)) {
            Map<Boolean, List<ProjectVO>> booleanListMap = ProjectGrouper.groupProjectsByScale(stop);
            extracted(list, booleanListMap);
        }
        List<ProjectVO> unStart = listMap.get("UN_START");
        if (!ObjectUtils.isEmpty(unStart)) {
            Map<Boolean, List<ProjectVO>> booleanListMap = ProjectGrouper.groupProjectsByScale(unStart);
            extracted(list, booleanListMap);
        }
        List<ProjectVO> die = listMap.get("DIE");
        if (!ObjectUtils.isEmpty(die)) {
            Map<Boolean, List<ProjectVO>> booleanListMap = ProjectGrouper.groupProjectsByScale(die);
            extracted(list, booleanListMap);
        }

        list.forEach(a -> {
            String streetCode = a.getStreetCode();
            String streetName = CommonUtil.streetMap.get(streetCode);
            if (!ObjectUtils.isEmpty(streetName)) {
                a.setJiansheAddress(streetName);
            }
        });
        return list;
    }

    private void extracted(List<ProjectVO> list, Map<Boolean, List<ProjectVO>> booleanListMap) {
        List<ProjectVO> up = booleanListMap.get(true);
        if (CollectionUtils.isNotEmpty(up)) {
            Map<String, List<ProjectVO>> collect = up.stream()
                    .collect(Collectors.groupingBy(ProjectVO::getEngineeringType));
            List<ProjectVO> gg = collect.get("PUBLIC_BUILDINGS");
            if (CollectionUtils.isNotEmpty(gg)) {
                Collections.sort(gg, new ScaleSizeComparator());
                list.addAll(gg);
            }
            List<ProjectVO> sp = collect.get("COMMERCIAL_HOUSING");
            if (CollectionUtils.isNotEmpty(sp)) {
                Collections.sort(sp, new ScaleSizeComparator());
                list.addAll(sp);
            }
            List<ProjectVO> bz = collect.get("AFFORDABLE_HOUSING");
            if (CollectionUtils.isNotEmpty(bz)) {
                Collections.sort(bz, new ScaleSizeComparator());
                list.addAll(bz);
            }
            List<ProjectVO> gy = collect.get("INDUSTRIAL_BUILDINGS");
            if (CollectionUtils.isNotEmpty(gy)) {
                Collections.sort(gy, new ScaleSizeComparator());
                list.addAll(gy);
            }
            List<ProjectVO> sz = collect.get("MUNICIPAL");
            if (CollectionUtils.isNotEmpty(sz)) {
                Collections.sort(sz, new ScaleSizeComparator());
                list.addAll(sz);
            }
            List<ProjectVO> zx = collect.get("DECORATION");
            if (CollectionUtils.isNotEmpty(zx)) {
                Collections.sort(zx, new ScaleSizeComparator());
                list.addAll(zx);
            }
            List<ProjectVO> lj = collect.get("HOUSE_ALTERATION");
            if (CollectionUtils.isNotEmpty(lj)) {
                Collections.sort(lj, new ScaleSizeComparator());
                list.addAll(lj);
            }
        }
        List<ProjectVO> down = booleanListMap.get(false);
        if (CollectionUtils.isNotEmpty(down)) {
            Map<String, List<ProjectVO>> collect = down.stream()
                    .collect(Collectors.groupingBy(ProjectVO::getEngineeringType));
            List<ProjectVO> gg = collect.get("PUBLIC_BUILDINGS");
            if (CollectionUtils.isNotEmpty(gg)) {
                Collections.sort(gg, new ScaleSizeComparator());
                list.addAll(gg);
            }
            List<ProjectVO> sp = collect.get("COMMERCIAL_HOUSING");
            if (CollectionUtils.isNotEmpty(sp)) {
                Collections.sort(sp, new ScaleSizeComparator());
                list.addAll(sp);
            }
            List<ProjectVO> bz = collect.get("AFFORDABLE_HOUSING");
            if (CollectionUtils.isNotEmpty(bz)) {
                Collections.sort(bz, new ScaleSizeComparator());
                list.addAll(bz);
            }
            List<ProjectVO> gy = collect.get("INDUSTRIAL_BUILDINGS");
            if (CollectionUtils.isNotEmpty(gy)) {
                Collections.sort(gy, new ScaleSizeComparator());
                list.addAll(gy);
            }
            List<ProjectVO> sz = collect.get("MUNICIPAL");
            if (CollectionUtils.isNotEmpty(sz)) {
                Collections.sort(sz, new ScaleSizeComparator());
                list.addAll(sz);
            }
            List<ProjectVO> zx = collect.get("DECORATION");
            if (CollectionUtils.isNotEmpty(zx)) {
                Collections.sort(zx, new ScaleSizeComparator());
                list.addAll(zx);
            }
            List<ProjectVO> lj = collect.get("HOUSE_ALTERATION");
            if (CollectionUtils.isNotEmpty(lj)) {
                Collections.sort(lj, new ScaleSizeComparator());
                list.addAll(lj);
            }
        }
    }

    private static class ScaleSizeComparator implements Comparator<ProjectVO> {
        @Override
        public int compare(ProjectVO p1, ProjectVO p2) {
            if ("MUNICIPAL".equals(p1.getEngineeringType()) && !"MUNICIPAL".equals(p2.getEngineeringType())) {
                // 按规模大小降序
                BigDecimal cost = p1.getEngineeringCost().multiply(new BigDecimal(10000));
                BigDecimal floorArea2 = p2.getFloorArea();
                return floorArea2.compareTo(cost);
            } else if (!"MUNICIPAL".equals(p1.getEngineeringType()) && "MUNICIPAL".equals(p2.getEngineeringType())) {
                // 按规模大小降序
                BigDecimal floorArea1 = p1.getFloorArea();
                BigDecimal cost = p2.getEngineeringCost().multiply(new BigDecimal(10000));
                return cost.compareTo(floorArea1);
            } else if ("MUNICIPAL".equals(p1.getEngineeringType()) && "MUNICIPAL".equals(p2.getEngineeringType())) {
                // 按规模大小降序
                BigDecimal cost1 = p1.getEngineeringCost().multiply(new BigDecimal(10000));
                BigDecimal cost2 = p2.getEngineeringCost().multiply(new BigDecimal(10000));
                return cost2.compareTo(cost1);
            } else {
                // 按规模大小降序
                BigDecimal floorArea1 = p1.getFloorArea();
                BigDecimal floorArea2 = p2.getFloorArea();
                return floorArea2.compareTo(floorArea1);
            }
        }
    }

    /**
     * 大屏右侧数据
     *
     * @param projectId
     * @return
     */
    @Override
    public Object getlargeScreenRight(Long projectId) {
        List<DictItemVO> personJob = dictItemService.queryDictItemByDictCode("USER_JOB");//人员职务
        ProjectDO projectDO = projectMapper.selectDOById(projectId);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("shigongUnit", projectDO.getShigongUnit());
        dataMap.put("jiansheUnit", projectDO.getJiansheUnit());
        dataMap.put("jianliUnit", projectDO.getJianliUnit());
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM.dd");
        LocalDate now = LocalDate.now();
        LocalDate lastMonday = now.minusWeeks(1).with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDate lastSunday = now.minusWeeks(1).with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        WeekFields weekFields = WeekFields.of(Locale.getDefault());
        int weekNumber = lastMonday.get(weekFields.weekOfWeekBasedYear());
        // 输出结果
        String time =
                lastMonday.getYear() + "年第" + weekNumber + "周（" + lastMonday.format(dateFormatter) + "-" + lastSunday.format(dateFormatter) + "）";
        dataMap.put("time", time);
        java.sql.Date startDate = java.sql.Date.valueOf(lastMonday);
        java.sql.Date endDate = java.sql.Date.valueOf(lastSunday);

        //项目人员统计
        List<String> personList = registrationMapper.selectCountPerson(projectId);
        Integer size = registrationMapper.selectProjectPersonCount(projectId);
        PageHomeKeyValue personCount = PageHomeKeyValue.builder().name("总数").value(size).build();
        Map<String, Long> personMap = personList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> personPageList = personMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(personJob.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        personPageList.add(personCount);
        dataMap.put("person", personPageList);
        //人员与作业统计
        Integer notLeave = registrationMapper.selectPerson(1, projectId, startDate.toString(), endDate.toString());//在场
        Integer leave = registrationMapper.selectPerson(0, projectId, startDate.toString(), endDate.toString());//离场
        Integer hotCount = hotWorkMapper.selectcounts(projectId, startDate, endDate);
        Integer inoculateNumber = registrationMapper.selectInoculateNumber(projectId, startDate.toString(),
                endDate.toString());
        dataMap.put("leaveCount", leave);
        dataMap.put("notLeaveCount", notLeave);
        dataMap.put("hotWorkCount", hotCount);
        dataMap.put("inoculateNumber", inoculateNumber);
        return dataMap;
    }

    /**
     * 统计分析
     *
     * @return
     */
    @Override
    public IndexStatisticalAnalysisVO getStatisticalAnalysis() {
        IndexStatisticalAnalysisVO.IndexStatisticalAnalysisVOBuilder builder = IndexStatisticalAnalysisVO.builder();
        Map<String, Object> map = new HashMap<>();
        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年M月d日");
        String formattedDate = currentDate.format(formatter);
        map.put("nowDate", formattedDate);
        builder.nowDate(formattedDate);
        // （一）建设工程复工复产情况
        // 1.基本信息
        fillP1Info(builder);
        // 2.复工信息
        fillP2Info(builder);
        // 3.停工信息
        fillP3Info(builder);
        // （二）施工现场人员统计
        fillP4Info(builder);

        return builder.build();
    }

    private void fillP4Info(IndexStatisticalAnalysisVO.IndexStatisticalAnalysisVOBuilder builder) {
        //全区工地在场人员合计（在施和完工状态项目的人）
        List<Map<String, Long>> notLeavePersonList = registrationMapper.selectAllNotLeavePerson();
        AtomicLong count = new AtomicLong(0);
        AtomicLong managerCount = new AtomicLong(0);
        AtomicLong workerCount = new AtomicLong(0);
        notLeavePersonList.forEach(a -> {
            count.addAndGet(a.get("num"));
            if ("MANAGER".equals(a.get("job_type"))) {
                managerCount.addAndGet(a.get("num"));
                //管理人员
                builder.managerCount(a.get("num"));
            }
            if ("WORKER".equals(a.get("job_type"))) {
                workerCount.addAndGet(a.get("num"));
                //工人
                builder.workerCount(a.get("num"));
            }
        });
        builder.notLeavePersonCount(count.get());

        //管理人员占比
        BigDecimal notLeavePersonCount = BigDecimal.valueOf(count.get());
        BigDecimal managerBig = BigDecimal.valueOf(managerCount.get());
        BigDecimal managerProportion = managerBig.divide(notLeavePersonCount, 4, BigDecimal.ROUND_HALF_UP);
        builder.managerProportion(managerProportion);

        //工人占比
        BigDecimal workerProportion = BigDecimal.valueOf(workerCount.get()).divide(notLeavePersonCount, 4,
                BigDecimal.ROUND_HALF_UP);
        builder.workerProportion(workerProportion);
        //后勤人员
        Long logistics = count.get() - managerCount.get() - workerCount.get();
        builder.logistics(logistics);
        //后勤人员占比
        BigDecimal logisticsProportion = BigDecimal.valueOf(logistics).divide(notLeavePersonCount, 4,
                BigDecimal.ROUND_HALF_UP);
        builder.logisticsProportion(logisticsProportion);
    }

    private void fillP3Info(IndexStatisticalAnalysisVO.IndexStatisticalAnalysisVOBuilder builder) {
        // 所有项目停工项目
        List<ProjectDO> stopProjectList = projectMapper.listByStatus(ConstructionStatusEnum.STOP.getCode());
        builder.stopProjectCount(stopProjectList.size());
        //停工率=停工项目/(停工项目+未停工项目)  未停工项目=RUNNING + WAIT_ACCEPT
        List<ProjectDO> totalList = projectMapper.listStopAndRunProject();
        BigDecimal totalSize = BigDecimal.valueOf(totalList.size());
        BigDecimal rate = BigDecimal.valueOf(stopProjectList.size()).divide(totalSize, 4, BigDecimal.ROUND_HALF_UP);
        builder.stopProjectRate(rate);
        //房建项目停工项
        Long houseMultiplexStopProject = stopProjectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.isHouseMultiplexProject(a.getEngineeringType()))
                .count();
        builder.houseMultiplexStopProject(houseMultiplexStopProject);
        //市政项目停工项
        Long municipalMultiplexStopCount = stopProjectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.MUNICIPAL.name().equals(a.getEngineeringType()))
                .count();
        builder.municipalMultiplexStopCount(municipalMultiplexStopCount);
        //装修工程停工项（装修和老旧小区改造之和）
        Long oldMultipleStopProjectCount = stopProjectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.isOldMultiplexCount(a.getEngineeringType()))
                .count();
        builder.oldMultipleStopProjectCount(oldMultipleStopProjectCount);

        //规模以上工程项目
        List<Map<String, Long>> upProjectCount = projectMapper.selectUpProjectList();
        AtomicLong allUp = new AtomicLong(0);
        AtomicLong upAndStartProjectSize = new AtomicLong(0);
        upProjectCount.forEach(map -> {
            allUp.addAndGet(map.get("num"));
            if (ConstructionStatusEnum.STOP.name().equals(map.get("status"))) {
                upAndStartProjectSize.addAndGet(map.get("num"));
            }
        });
        builder.upProjectSum(allUp.get());
        //规模以上已停工项目
        builder.upAndStopProject(upAndStartProjectSize.get());
        //规模以下工程项目
        List<Map<String, Long>> downProjectCount = projectMapper.selectDownProjectList();
        AtomicLong allDown = new AtomicLong(0);
        AtomicLong downCount = new AtomicLong(0);
        downProjectCount.forEach(a -> {
            allDown.addAndGet(a.get("num"));
            if (ConstructionStatusEnum.STOP.name().equals(a.get("status"))) {
                downCount.addAndGet(a.get("num"));
            }
        });
        builder.downProjectSum(allDown.get());
        //规模以下已复工项
        builder.downAndStopProject(downCount.get());
    }

    private void fillP2Info(IndexStatisticalAnalysisVO.IndexStatisticalAnalysisVOBuilder builder) {
        //已复工项目
        List<ProjectDO> multiplexProjectList = projectMapper.selectMultiplexProjectList();
        builder.multiplexProjectList(multiplexProjectList.size());
        //完工待验项
        Long completeProject = multiplexProjectList.stream()
                .filter(a -> ConstructionStatusEnum.WAIT_ACCEPT.name().equals(a.getConstructionStatus()))
                .count();
        builder.completeProject(completeProject);
        //未复工项
        List<ProjectDO> notMultiplexProjectList = projectMapper.selectNotMultiplexProjectList();
        builder.notMultiplexProjectList(notMultiplexProjectList.size());
        //复工率
        BigDecimal totalSize = BigDecimal.valueOf(multiplexProjectList.size() + notMultiplexProjectList.size());
        BigDecimal result = BigDecimal.valueOf(multiplexProjectList.size()).divide(totalSize, 4,
                BigDecimal.ROUND_HALF_UP);
        builder.resumptionRate(result);
        //房建项目复工项
        Long houseMultiplexProject = multiplexProjectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.isHouseMultiplexProject(a.getEngineeringType()))
                .count();
        builder.houseMultiplexProject(houseMultiplexProject);
        //市政项目复工项
        Long municipalMultiplexCount = multiplexProjectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.MUNICIPAL.name().equals(a.getEngineeringType()))
                .count();
        builder.municipalMultiplexCount(municipalMultiplexCount);
        //装修工程复工项（装修和老旧小区改造之和）
        Long oldMultiplexCount = multiplexProjectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.isOldMultiplexCount(a.getEngineeringType()))
                .count();
        builder.oldMultiplexCount(oldMultiplexCount);

        //规模以上工程项
        List<Map<String, Long>> upProjectCount = projectMapper.selectUpProjectList();
        AtomicLong allUp = new AtomicLong(0);
        AtomicLong upAndStartProjectSize = new AtomicLong(0);
        upProjectCount.forEach(a -> {
            allUp.addAndGet(a.get("num"));
            if ("RUNNING".equals(a.get("status")) || "WAIT_ACCEPT".equals(a.get("status"))) {
                upAndStartProjectSize.addAndGet(a.get("num"));
            }
        });
        builder.upProjectCount(allUp.get());
        //规模以上已复工项
        builder.upAndStartProject(upAndStartProjectSize.get());
        //规模以下工程
        List<Map<String, Long>> downProjectCount = projectMapper.selectDownProjectList();
        AtomicLong allDown = new AtomicLong(0);
        AtomicLong downCount = new AtomicLong(0);
        downProjectCount.forEach(a -> {
            allDown.addAndGet(a.get("num"));
            if ("RUNNING".equals(a.get("status")) || "WAIT_ACCEPT".equals(a.get("status"))) {
                downCount.addAndGet(a.get("num"));
            }
        });
        builder.downProjectCount(allDown.get());
        //规模以下已复工项
        builder.downAndStartProject(downCount.get());
    }

    private void fillP1Info(IndexStatisticalAnalysisVO.IndexStatisticalAnalysisVOBuilder builder) {
        //在监工程
        List<ProjectDO> projectList = projectMapper.selectStartProject();
        builder.inPrison(projectList.size());
        //房建工程项
        List<ProjectDO> house = projectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.isHouseMultiplexProject(a.getEngineeringType()))
                .collect(Collectors.toList());
        builder.houseProjectCount(house.size());
        //建筑规模
        BigDecimal houseFloorArea = house.stream()
                .map(ProjectDO::getFloorArea)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(10000), 2, BigDecimal.ROUND_HALF_UP);
        builder.houseFloorArea(houseFloorArea);
        //市政工程项
        List<ProjectDO> municipalCount =
                projectList.stream()
                        .filter(a -> ProjectEngineeringTypeEnum.MUNICIPAL.name().equals(a.getEngineeringType()))
                        .collect(Collectors.toList());
        builder.municipalCount(municipalCount.size());
        //市政工程总造价
        BigDecimal municipalEngineeringCost = municipalCount.stream()
                .map(ProjectDO::getEngineeringCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(10000), 2, BigDecimal.ROUND_HALF_UP);
        builder.municipalEngineeringCost(municipalEngineeringCost);
        //装修工程项
        List<ProjectDO> fitmentCount = projectList.stream()
                .filter(a -> ProjectEngineeringTypeEnum.DECORATION.name().equals(a.getEngineeringType()))
                .collect(Collectors.toList());
        builder.fitmentCount(fitmentCount.size());
        //装修项面积
        BigDecimal fitmentFloorArea = fitmentCount.stream()
                .map(ProjectDO::getFloorArea)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(10000), 2, BigDecimal.ROUND_HALF_UP);
        builder.fitmentFloorArea(fitmentFloorArea);
        //老旧小区项
        List<ProjectDO> oldPlotCount =
                projectList.stream()
                        .filter(a -> ProjectEngineeringTypeEnum.HOUSE_ALTERATION.name().equals(a.getEngineeringType()))
                        .collect(Collectors.toList());
        builder.oldPlotCount(oldPlotCount.size());
        //老旧小区面积
        BigDecimal oldPlotFloorArea = oldPlotCount.stream()
                .map(ProjectDO::getFloorArea)
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(10000), 2, BigDecimal.ROUND_HALF_UP);
        builder.oldPlotFloorArea(oldPlotFloorArea);
    }

    @Override
    public Object getSuperviseHomepageOne() {
        List<DictItemVO> buildStatus = dictItemService.queryDictItemByDictCode("BUILD_TYPE");//施工状态
        //工程状态统计
        List<String> projectList = projectMapper.selectAllBuildStatus();
        Map<String, Long> statusMap = projectList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> resultList = statusMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(buildStatus.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        PageHomeKeyValue statusCount = PageHomeKeyValue.builder().name("总数").value(projectList.size()).build();
        resultList.add(statusCount);
        return SuperviseHomePageVO.builder().projectStatusList(resultList).build();
    }

    @Override
    public Object getSuperviseHomepageTwo() {
        //工程类型统计
        List<String> typeList = projectMapper.selectAllBuildType();
        List<DictItemVO> buildsType = dictItemService.queryDictItemByDictCode("PROJECT_TYPE");//工程类型
        Map<String, Long> typeMap = typeList.stream().collect(Collectors.groupingBy(item -> item,
                Collectors.counting()));
        List<PageHomeKeyValue> typePageList = typeMap.entrySet().stream()
                .map(entry -> new PageHomeKeyValue(buildsType.stream().filter(dictItemVO -> entry.getKey().equals(dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry.getValue()))
                .collect(Collectors.toList());
        PageHomeKeyValue typeCount = PageHomeKeyValue.builder().name("总数").value(typeList.size()).build();
        typePageList.add(typeCount);
        return SuperviseHomePageVO.builder().projectTypeList(typePageList).build();
    }

    @Override
    public Object getSuperviseHomepageThree() {
        List<DictItemVO> personJob = dictItemService.queryDictItemByDictCode("USER_JOB");//人员职务
        //项目人员分布
        List<Map<String, Object>> personList = registrationMapper.selectProjectPerson();
//        Map<String, Long> personMap  = personList.stream().collect(Collectors.groupingBy(item -> item, Collectors
//        .counting()));
//        List<PageHomeKeyValue> personPageList = personMap.entrySet().stream()
//                .map(entry -> new PageHomeKeyValue(personJob.stream().filter(dictItemVO -> entry.getKey().equals
//                (dictItemVO.getDictItemCode())).findFirst().orElse(new DictItemVO()).getDictItemCode(), entry
//                .getValue()))
//                .collect(Collectors.toList());
        AtomicLong all = new AtomicLong(0);
        List<PageHomeKeyValue> list = new ArrayList<>();
        personList.forEach(a -> {
            all.addAndGet((Long) a.get("num"));
            PageHomeKeyValue keyValue = new PageHomeKeyValue();
            keyValue.setName(String.valueOf(a.get("name")));
            keyValue.setValue(a.get("num"));
            list.add(keyValue);
        });
        PageHomeKeyValue personCount = PageHomeKeyValue.builder().name("总数").value(all.get()).build();
        list.add(personCount);
        return SuperviseHomePageVO.builder().projectPersonList(list).build();
    }

    @Override
    public Object getSuperviseHomepageFour() {
        //最近八周的时间范围
        List<Map<String, Date>> weekRanges = getWeekRanges();

        List<String> weekRange = getWeekRange();
        List<Integer> notLeave = new ArrayList<>();
        List<Integer> leave = new ArrayList<>();
        //全区项目人员流动性统计
        weekRanges.forEach(week -> {
            Date startDate = week.get("startDate");
            Date endDate = week.get("endDate");
            //在场
            Integer leaveCount = registrationMapper.selectEightWeeklyData(1, null, startDate.toString(),
                    endDate.toString());
            //离场
            Integer notLeaveCount = registrationMapper.selectEightWeeklyData(0, null, startDate.toString(),
                    endDate.toString());
            notLeave.add(notLeaveCount);
            leave.add(leaveCount);
        });
        Map<String, Object> flowMap = new HashMap<>();
        flowMap.put("notLeave", leave);
        flowMap.put("leave", notLeave);
        flowMap.put("weeks", weekRange);
        return SuperviseHomePageVO.builder().projectPersonFlowMap(flowMap).build();
    }

    @Override
    public Object getSuperviseHomepageFive() {
        List<Map<String, Date>> weekRanges = getWeekRanges();
        List<String> weekRange = getWeekRange();
        //全区动火作业统计
        List<Integer> hotWorkData = new ArrayList<>();
        weekRanges.forEach(week -> {
            Date startDate = week.get("startDate");
            Date endDate = week.get("endDate");
            Integer dateList = hotWorkMapper.selectEightWeeklyData(null, startDate, endDate);
            hotWorkData.add(dateList);
        });
        Map<String, Object> hotWorkMap = new HashMap<>();
        hotWorkMap.put("hotWorkData", hotWorkData);
        hotWorkMap.put("weeks", weekRange);
        return SuperviseHomePageVO.builder().projectHotWorkCountMap(hotWorkMap).lastDate(DateUtils.getNowDate()).build();
    }

    /**
     * 将时间字符串集合以周为单位分割，并统计处于统计周的数据条数
     *
     * @param list
     */
    private Map<String, Integer> getDate(List<String> list) {
        // 转换为日期对象
        List<LocalDate> dates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        for (String dateStr : list) {
            LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
            dates.add(dateTime.toLocalDate());
        }

        // 创建一个映射来存储结果
        Map<String, Integer> result = new TreeMap<>();

        // 遍历日期
        for (LocalDate date : dates) {
            // 计算日期所在的周
            String year = Integer.toString(date.getYear());
            String week = Integer.toString(date.get(WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear()) - 1);

            // 计算周的开始和结束日期
            LocalDate start = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            LocalDate end = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
            String replace1 = start.toString().replace('-', '/');
            String replace = end.toString().replace('-', '/');

            // 更新结果
            String key = year + "年第" + week + "周: " + replace1 + "-" + replace;

            if (result.containsKey(key)) {
                result.put(key, result.get(key) + 1);
            } else {
                result.put(key, 1);
            }
        }
        return result;
    }

    /**
     * 获取查询的时间范围
     *
     * @return
     */
    public static List<Map<String, Date>> getWeekRanges() {
        List<Map<String, Date>> weekRanges = new ArrayList<>();

        LocalDate currentDate = LocalDate.now();

        for (int i = 0; i <= 7; i++) {
            LocalDate startOfWeek = currentDate.minusWeeks(i).with(DayOfWeek.MONDAY);
            LocalDate endOfWeek = currentDate.minusWeeks(i).with(DayOfWeek.SUNDAY);

            Map<String, Date> range = new HashMap<>();
            range.put("startDate", java.sql.Date.valueOf(startOfWeek));
            range.put("endDate", java.sql.Date.valueOf(endOfWeek));

            weekRanges.add(range);
        }
        Collections.reverse(weekRanges);
        return weekRanges;
    }

    /**
     * 返回的时间范围值
     *
     * @return
     */
    public static List<String> getWeekRange() {
        List<String> weekRanges = new ArrayList<>();

        LocalDate currentDate = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd", Locale.getDefault());

        Map<Integer, String> map = new HashMap<>();
        List<WeekRangeDTO> weekRangeDTOList = Lists.newArrayList();
        for (int i = 0; i <= 7; i++) {
            LocalDate startOfWeek = currentDate.minusWeeks(i).with(DayOfWeek.MONDAY);
            LocalDate endOfWeek = currentDate.minusWeeks(i).with(DayOfWeek.SUNDAY);

            int weekOfYear = startOfWeek.get(WeekFields.of(Locale.getDefault()).weekOfWeekBasedYear());
            String range = startOfWeek.format(formatter) + "-" + endOfWeek.format(formatter);

            map.put(weekOfYear, range);
            weekRangeDTOList.add(WeekRangeDTO.builder().weekOfYear(weekOfYear).range(range).build());
        }

        //List<Map.Entry<Integer, String>> sortedList = new ArrayList<>(map.entrySet());
        //Collections.sort(sortedList, Comparator.comparingInt(Map.Entry::getKey));
        //
        //for (Map.Entry<Integer, String> entry : sortedList) {
        //    String weekRange = "第" + entry.getKey() + "周: " + entry.getValue();
        //    weekRanges.add(weekRange);
        //}
        Collections.reverse(weekRangeDTOList);
        for (WeekRangeDTO weekRangeDTO : weekRangeDTOList) {
                String weekRange = "第" + weekRangeDTO.getWeekOfYear() + "周: " + weekRangeDTO.getRange();
                weekRanges.add(weekRange);
        }

        return weekRanges;
    }
}
